﻿#region Description
/*  File Name:      MenuScreen.cs
 *  Author:         Adam Goodchild
 *  
 *  Description:    This is a Class used for a Menu, allowing users to select
 *                  options (MenuEntry's)
 *  
 *  Sources:        The Idea for this class was gained from the following source(s):
 *                  Microsoft XNA Creators Club - Game State Management Sample
*/
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinimizeEngine.Screens;
using MinimizeEngine.Menu_System;
using MinimizeEngine.Managers;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace MinimizeEngine.Menu_System
{
    public abstract class MEMenuScreen : MEBaseScreen
    {
        #region Fields

        List<MEMenuEntry> mMenuEntries = new List<MEMenuEntry>();
        
        int mSelectedEntry = 0;

        string mMenuTitleText;

        bool m_bIsAnimated;

        #endregion

        #region Properties

        /// <summary>
        /// Gets a list of the Menu Entries
        /// Allows other classes, based upon this class, to add and edit
        /// the contents of the Menu System
        /// </summary>
        public IList<MEMenuEntry> MenuEntries
        {
            get { return mMenuEntries; }
        }

        /// <summary>
        /// Determines whether the Menu Screen is animated or not
        /// This will make each Menu Entry Animate if set to True
        /// </summary>
        public bool IsAnimated
        {
            get { return m_bIsAnimated; }
            set { m_bIsAnimated = value; }
        }

        #endregion

        #region Initialization

        /// <summary>
        /// Constructs a new Menu Screen
        /// </summary>
        /// <param name="menuTitle"></param>
        public MEMenuScreen(string menuTitle, bool isAnimated)
        {
            //Set the Menu Title Text
            mMenuTitleText = menuTitle;

            //Set the bool for Animation of Menu Entries
            m_bIsAnimated = isAnimated;

            TransitionOnTime = TimeSpan.FromSeconds(0.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }

        #endregion

        #region Handle Input

        /// <summary>
        /// Handles User Input.
        /// Handles the movement between Menu Entries, Selecting a Menu Entry
        /// or canceling out of a Menu.
        /// </summary>
        /// <param name="inputState"></param>
        public override void HandleInput(MEInputManager inputManager)
        {
            //Are we moving to the Previous Menu Entry?
            if(inputManager.IsMenuOptionUp())
            {
                //Move the Selected Entry Up
                mSelectedEntry--;

                //If we are at the top, and we move up
                //then move to the bottom Menu Entry
                if(mSelectedEntry < 0)
                {
                    mSelectedEntry = mMenuEntries.Count - 1;
                }
            }

            //Are we moving to the Next Menu Entry?
            if(inputManager.IsMenuOptionDown())
            {
                //Move the Selected Entry Down
                mSelectedEntry++;

                //If we are at the bottom, and we move down
                //then move to the top Menu Entry
                if (mSelectedEntry >= mMenuEntries.Count)
                {
                    mSelectedEntry = 0;
                }
            }

            //Are we Selecting a Menu Entry
            if(inputManager.IsMenuOptionSelected())
            {
                OnEntrySelected(mSelectedEntry);
            }
            //Or are we Canceling out of the Menu Screen
            else if(inputManager.IsMenuOptionCancel())
            {
                OnMenuScreenCanceled();
            }
        }

        /// <summary>
        /// Handles the Selection of a Menu Entry
        /// </summary>
        /// <param name="selectedMenuEntry"></param>
        /// <param name="playerIndex"></param>
        protected virtual void OnEntrySelected(int selectedMenuEntry)
        {
            mMenuEntries[selectedMenuEntry].OnMenuEntrySelected();
        }

        /// <summary>
        /// Handles when the Player Cancels out of the Menu Screen
        /// </summary>
        /// <param name="playerIndex"></param>
        protected virtual void OnMenuScreenCanceled()
        {
            ExitScreen();
        }

        /// <summary>
        /// Handles when the Player Cancels out of the Menu Screen
        /// </summary>
        /// <param name="playerIndex"></param>
        protected virtual void OnMenuScreenCanceled(object sender, EventArgs eventArgs)
        {
            OnMenuScreenCanceled();
        }

        #endregion

        #region Update

        /// <summary>
        /// Updates the Menu Screen
        /// </summary>
        /// <param name="gameTime"></param>
        /// <param name="otherScreenHasFocus"></param>
        /// <param name="coveredByOtherScreen"></param>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            //Update all of the Menu Entries
            for(int i = 0; i < mMenuEntries.Count; i++)
            {
                //Check to see if the Menu Entry is Selected
                bool isEntrySelected = IsActive && (i == mSelectedEntry);

                mMenuEntries[i].Update(gameTime, isEntrySelected, this);
            }
        }

        #endregion

        #region Draw

        /// <summary>
        /// Draw the Menu Screen
        /// This will draw all Menu Entries in the Menu Screen
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Draw(GameTime gameTime)
        {
            //Get the Sprite Batch from the Screen Manager
            SpriteBatch spriteBatch = MEScreenManager.SpriteBatch;

            //Get the Font from the Screen Manager
            SpriteFont spriteFont = MEScreenManager.Font;

            //The Default Position to draw the Menu Entry
            Vector2 menuEntryPosition = new Vector2(100, 150);

            //During Transitions, make sure the Menu slides into its place.
            //Using a Power Curve, the slide will slow down towards the end.
            float transPowerCurve = (float)Math.Pow(TransitionPosition, 2);

            //Are we Transitioning On?
            if(ScreenState == ScreenState.TransitionOn)
            {
                menuEntryPosition.X -= transPowerCurve * 256;
            }
            else
            {
                menuEntryPosition.X += transPowerCurve * 512;
            }

            spriteBatch.Begin();

            //Draw each Menu Entry
            for (int i = 0; i < mMenuEntries.Count; i++)
            {
                //Get the current Menu Entry
                MEMenuEntry menuEntry = mMenuEntries[i];

                //Check to see if the Menu Entry is Selected
                bool isEntrySelected = IsActive && (i == mSelectedEntry);

                //Now Draw the Menu Entry
                menuEntry.Draw(gameTime, this, menuEntryPosition, isEntrySelected);

                //Update the Menu Entry Position for the next Menu Entry to be Drawn
                menuEntryPosition.Y += menuEntry.GetHeight(this);
            }

            //Now Draw the Menu Title
            Vector2 menuTitlePosition = new Vector2(MEEngineManager.DeviceManager.GraphicsDevice.Viewport.Width / 2, 80);
            Vector2 menuTitleOrigin = spriteFont.MeasureString(mMenuTitleText) / 2;
            Color menuTitleColour = Color.White;
            float menuTitleScale = 1.25f;

            //Update the Menu Titles Y Position
            menuTitlePosition.Y -= transPowerCurve * 100;

            //Draw the Text
            spriteBatch.DrawString(spriteFont, mMenuTitleText, menuTitlePosition, menuTitleColour, 0,
                menuTitleOrigin, menuTitleScale, SpriteEffects.None, 0);
            
            spriteBatch.End();
        }

        #endregion
    }
}
